<!--
 * @Author: wupeiwen <javapeiwen2010@gmail.com>
 * @Date: 2022-04-21 17:49:14
 * @LastEditors: wupeiwen <javapeiwen2010@gmail.com>
 * @LastEditTime: 2023-10-24 14:03:54
 * @FilePath: /tea-garden-web/src/components/component-map.vue
 * @Description: 组件-地图
-->
<template>
  <div class="component-map">
    <div class="map" id="map"></div>
    <div id="popup" class="popup">
      <div v-html="popupCntent"></div>
      <div class="player" v-show="showVideo">
        <video ref="videoPlayer"
          :src="videoUrl"
          id="videoPlayer"
          controls
          muted
          style="width: 100%; height: 150px;
          object-fit: fill"
        >
        </video>
      </div>
    </div>
    <component-map-button-group class="map-button-group" />
  </div>
</template>

<script>
import 'ol/ol.css'
import Map from 'ol/Map'
import WMTSSource, { optionsFromCapabilities } from 'ol/source/WMTS'
import WMTSCapabilities from 'ol/format/WMTSCapabilities'
import { XYZ as XYZSource, Vector as VectorSource } from 'ol/source'
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
// import { Select } from 'ol/interaction'
import { GeoJSON } from 'ol/format'
import { Style, Stroke, Fill, Text, Icon } from 'ol/style'
import View from 'ol/View'
import Overlay from 'ol/Overlay'
import { color2, windDri2, windSpeed2, formatDate } from '@/util/dict.js'
import { mapGetters, mapState, mapMutations, mapActions } from 'vuex'
import { get } from '@/util/http.js'
import hlsjs from 'hls.js'
// import EZUIKit from 'ezuikit-js'
export default {
  data () {
    return {
      map: null,
      layerZ1: null,
      layerZ2: null,
      layerZ3: null,
      layerZ4: null,
      overlay: null,
      popupCntent: '',
      videoUrl: null,
      showVideo: false,
      hlsjs: null
    }
  },
  watch: {
    layers: {
      handler (val) {
        if (val.equipment) {
          this.layerZ4.setVisible(true)
        } else {
          this.layerZ4.setVisible(false)
        }
        if (val.farmland) {
          this.layerZ3.setVisible(true)
        } else {
          this.layerZ3.setVisible(false)
        }
      },
      deep: true
    },
    $route (val) {
      // 概览模块，地图显示所有地块以及传感器
      // console.log(val)
      if (val.path === '/base-overview/portal') {
        this.visableEquipmentleLayer(true)
        this.setStyle()
      }
      // 地块管理模块，地图显示所有地块以及地块编号
      if (val.path === '/base-overview/farmland-search') {
        this.visableEquipmentleLayer(false)
        this.setStyle2()
      }
    },
    farmlandGrowth (val) {
      this.visableEquipmentleLayer(false)
      this.setStyle(val, 'massif_id', 'degree')
      this.setStyle2()
    },
    pickDistribute (val) {
      this.visableEquipmentleLayer(false)
      this.setStyle(val, 'area_id', 'level', 'pickingstarttime')
      // this.setStyle2()
    },
    farmlandDisease (val) {
      this.visableEquipmentleLayer(false)
      this.setStyle(val, 'massif_id', 'degree')
      // this.setStyle2()
    },
    farmlandWeatherWarn (val) {
      this.visableEquipmentleLayer(false)
      this.setStyle(val, 'area_id', 'level')
      // this.setStyle2()
    }
  },
  computed: {
    ...mapState('base-overview', ['baseInfo', 'layers', 'legends', 'realTimeWeatherFromCMA', 'token', 'realTimeSoilState']),
    ...mapGetters('base-overview', ['formatAllFarmland', 'formatAllEquipment']),
    ...mapState('subject-growth', ['farmlandGrowth']),
    ...mapState('subject-pick', ['pickDistribute']),
    ...mapState('subject-disease', ['farmlandDisease']),
    ...mapState('subject-weather', ['farmlandWeatherWarn']),
    ...mapGetters('common', ['getDictItemNameById'])
  },
  beforeUnmount () {
    if (this.hlsjs) {
      this.$refs.videoPlayer.pause()
      this.$refs.videoPlayer = null
      this.hlsjs.destroy()
      this.hlsjs = null
    }
  },
  methods: {
    ...mapMutations('base-overview', ['setFarmlandId', 'setLayersOrLegends']),
    ...mapActions('base-overview', ['getRealTimeWeatherFromCMA', 'getToken', 'getRealTimeSoilState']),
    async initMap () {
      // const res = await fetch('http://39.105.35.32:8183/geoserver/gwc/service/wmts/wmts?REQUEST=GetCapabilities')
      const res = await fetch('http://115.29.207.19:10011/geoserver/gwc/service/wmts/wmts?REQUEST=GetCapabilities')
      const resText = await res.text()
      const capabilities = (new WMTSCapabilities()).read(resText)
      const options = optionsFromCapabilities(capabilities, {
        layer: 'songyangMap:lvmingfeng',
        matrixSet: 'EPSG:4326'
      })
      options.urls[0] = options.urls[0].replace('39.105.35.32', '39.105.35.32:8183')
      this.layerZ1 = new TileLayer({
        title: '天地图影像图层',
        source: new XYZSource({
          url: 'http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=7cee8dffaefd3bc825da6196385a20dd',
          wrapX: false,
          minZoom: 16,
          maxZoom: 17
        })
      })
      this.layerZ2 = new TileLayer({
        title: '无人机影像图层',
        source: new WMTSSource(options)
      })
      this.layerZ3 = new VectorLayer({
        title: '地块图层',
        source: new VectorSource({
          features: new GeoJSON().readFeatures(this.formatAllFarmland)
        }),
        style: (feature) => {
          return new Style({
            stroke: new Stroke({
              color: 'rgba(255, 255, 255, 0.7)',
              width: 2.5,
              lineDash: [6]
            }),
            fill: new Fill({
              color: 'rgba(255, 255, 255, 0)'
            }),
            text: new Text({
              text: feature.get('massif_num'),
              font: '12px sans-serif',
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 3 }),
              textAlign: 'center'
            })
          })
        }
      })

      this.layerZ4 = new VectorLayer({
        title: '设备图层',
        source: new VectorSource({
          features: new GeoJSON().readFeatures(this.formatAllEquipment)
        }),
        style: (feature) => {
          const type = feature.get('type_')
          return new Style({
            image: new Icon({
              anchor: [1, 1],
              // scale: 0.8,
              width: 28,
              height: 40,
              src: `/image/equipment/icon-${type}.png`
            })
          })
        }
      })
      this.map = new Map({
        layers: [this.layerZ1, this.layerZ2, this.layerZ3, this.layerZ4],
        target: 'map',
        view: new View({
          center: [119.33992, 28.49189],
          projection: 'EPSG:4326',
          zoom: 18.6
        })
      })
      let previousFeature = null
      // 点击事件
      this.map.on('click', async (evt) => {
        if (previousFeature) {
          // 这里应用初始的或默认的样式
          previousFeature.setStyle(undefined)
        }
        // console.log(evt)
        const feature = this.map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => feature)

        // 检查该特征是否是地块图层的一部分
        if (feature && feature.getGeometry().getType() === 'Polygon') {
          // 创建一个新样式，改变 stroke 颜色
          const newStyle = new Style({
            // 边框色
            stroke: new Stroke({
              color: 'yellow', // 可以设置为其他所需的颜色
              width: 2.5,
              lineDash: [6]
            }),
            fill: new Fill({
              color: 'rgba(255, 255, 255, 0.1)'
            }),
            text: new Text({
              text: feature.get('massif_num'),
              font: '12px sans-serif',
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 3 }),
              textAlign: 'center'
            })
          })

          // 应用新的样式到 feature
          feature.setStyle(newStyle)

          // 更新上一个 feature 为当前 feature
          previousFeature = feature
        }

        // 点击地块，左侧控制面板出现对应数据
        // console.log(feature)
        if (feature && feature.values_.massif_num !== undefined) {
          this.handleClickFarmland(feature.values_.id)
        }

        const overlay = new Overlay({
          element: document.getElementById('popup'),
          autoPan: true,
          autoPanAnimation: {
            duration: 250
          }
        })

        this.map.addOverlay(overlay)
        this.showVideo = false
        if (feature && feature.get('type_')) {
          const type = this.getDictItemNameById(feature.get('type_'))
          this.popupCntent = '<p>' + type + '</p>'
          if (feature.get('type_') === 94) {
            this.popupCntent += '<p>状态:&nbsp;正常</p>'
          }
          if (feature.get('type_') === 93) {
            this.popupCntent += '<p>状态:&nbsp;正常</p>'
          }
          if (feature.get('type_') === 92) {
            // this.popupCntent += '<p>状态:&nbsp;离线（局域网设备）</p>'
            // this.popupCntent += '<iframe id="myiframe" width="240" src="http://39.105.35.32:8083/#/video"></iframe>'
            this.popupCntent += ''
            this.showVideo = true
            this.$nextTick(() => {
              this.videoGet(2)
            })
          }
          if (feature.get('type_') === 1188) {
            this.popupCntent += ''
            this.showVideo = true
            this.$nextTick(() => {
              this.videoGet(4)
            })
          }
          if (feature.get('type_') === 91) {
            await this.getRealTimeWeatherFromCMA()
            const weather = this.realTimeWeatherFromCMA
            this.popupCntent += '<p>更新时间:&nbsp;' + formatDate(weather.DATETIME) + '</p>'
            this.popupCntent += '<p>温度:&nbsp;' + weather.TEM + '℃</p>'
            this.popupCntent += '<p>湿度:&nbsp;' + weather.RHU + '%</p>'
            this.popupCntent += '<p>风向风速:&nbsp;' + windDri2(weather.WIND) + windSpeed2(weather.WINS) + '</p>'
            this.popupCntent += '<p>1小时累计降水(10分钟):&nbsp;' + weather.PRE_1H + 'mm</p>'
            this.popupCntent += '<p>3小时累计降水(10分钟):&nbsp;' + weather.PRE_3H + 'mm</p>'
            this.popupCntent += '<p>6小时累计降水(10分钟):&nbsp;' + weather.PRE_6H + 'mm</p>'
            this.popupCntent += '<p>12小时累计降水(10分钟):&nbsp;' + weather.PRE_12H + 'mm</p>'
            this.popupCntent += '<p>24小时累计降水(10分钟):&nbsp;' + weather.PRE_24H + 'mm</p>'
            this.popupCntent += '<p>总云量:&nbsp;' + weather.TCDC + '%</p>'
            this.popupCntent += '<p>能见度:&nbsp;' + weather.VIS + 'm</p>'
          }
          if (feature.get('type_') === 90) {
            await this.getRealTimeSoilState()
            const data = this.realTimeSoilState
            const d2Name = data[0][1]
            const d2Data = data[1][d2Name]
            const that = this
            for (const key in d2Data) {
              if (Object.hasOwnProperty.call(d2Data, key)) {
                const item = d2Data[key]
                // console.log(item)
                that.popupCntent += '<p>' + item.name.replace(/①/g, '') + ':&nbsp;' + item.appValue + item.com + '</p>'
              }
            }
          }
          if (feature.get('type_') === 89) {
            this.popupCntent += '<p>通道1:&nbsp;0.05&nbsp&nbsp'
            this.popupCntent += '通道2:&nbsp;0.05<br>'
            this.popupCntent += '通道3:&nbsp;0.04&nbsp&nbsp'
            this.popupCntent += '通道4:&nbsp;0.05<br>'
            this.popupCntent += '通道5:&nbsp;0.33&nbsp&nbsp'
            this.popupCntent += '通道6:&nbsp;0.44</p>'
            this.popupCntent += `<img width="240px" src="${'http://121.40.144.89/pic/000000005bbdff06/2023_07_23_12_30_38_pic.jpg'}" />`
          }
          overlay.setPosition(evt.coordinate)
        } else {
          this.map.removeOverlay(overlay)
        }
      })
      // 隐藏地图缩放控件
      this.map.getControls().getArray()[0].element.style.display = 'none'
    },
    // 获取视频链接
    async videoGet (videoChannelNo) {
      // const myPlayer = this.$refs.videoPlayer.player
      if (this.videoUrl) {
        return
      }
      get({ url: '/device/getMonitorURL', params: { channelNo: videoChannelNo, deviceSerial: 'K60273702' } }).then(async res => {
        this.videoUrl = res.url
        const video = await this.$refs.videoPlayer
        if (hlsjs.isSupported()) {
          this.hlsjs = await new hlsjs()
          this.hlsjs.loadSource(this.videoUrl)
          this.hlsjs.attachMedia(video)
          this.hlsjs.on(hlsjs.Events.MANIFEST_PARSED, () => {
            video.play()
          })
          this.hlsjs.on(hlsjs.Events.ERROR, (event, data) => {
            console.log('加载失败')
          })
        }
        // state.value.urls = res.Content
        // new EZUIKit.EZUIKitPlayer({
        //   autoplay: true,
        //   id: 'videoPlayer', // 播放控件的ID
        //   accessToken: res.token, // 后端给的Token
        //   url: 'ezopen://open.ys7.com/K60273702/1.hd.live', // 后端给的URL
        //   template: 'simple', // simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版；
        //   plugin: ['talk']
        // })
      })
    },
    // 触发调整事件
    handleClickFarmland (farmlandId) {
      this.setFarmlandId(farmlandId)
      this.$router.push({ name: 'farmlandDetail' })
    },
    hexToRGBA (hex, alpha) {
      const r = parseInt(hex.slice(1, 3), 16)
      const g = parseInt(hex.slice(3, 5), 16)
      const b = parseInt(hex.slice(5, 7), 16)
      if (alpha) {
        return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')'
      } else {
        return 'rgb(' + r + ', ' + g + ', ' + b + ')'
      }
    },
    // 地图样式
    setStyle (val, key1, key2, key3) {
      if (val && val.length > 0) {
        const valObj = {}
        const valObj2 = {}
        val.map(item => {
          valObj[item[key1]] = item[key2]
          valObj2[item[key1]] = item[key3]
          return item
        })
        this.layerZ3.getSource().getFeatures().map(feature => {
          const hex = color2[valObj[feature.get('id')]] || '#ffffff'
          const rgba = this.hexToRGBA(hex, 0.1)
          feature.setStyle(new Style({
            stroke: new Stroke({
              color: hex,
              width: 2.5,
              lineDash: [6]
            }),
            fill: new Fill({
              color: hex === '#ffffff' ? 'rgba(255, 255, 255, 0.1)' : rgba
            }),
            text: new Text({
              text: feature.get('massif_num'),
              font: '12px sans-serif',
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 3 }),
              textAlign: 'center'
            })
          }))
          return feature
        })
      } else {
        this.layerZ3.getSource().getFeatures().map(feature => {
          // console.log(feature, 308)
          feature.setStyle(new Style({
            stroke: new Stroke({
              color: 'rgba(255, 255, 255, 0.7)',
              width: 2.5,
              lineDash: [6]
            }),
            fill: new Fill({
              color: 'rgba(255, 255, 255, 0.1)'
            }),
            text: new Text({
              text: feature.get('massif_num'),
              font: '12px sans-serif',
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 3 }),
              textAlign: 'center'
            })
          }))
          return feature
        })
      }
    },
    setStyle2 () {
      this.layerZ3.getSource().getFeatures().map(feature => {
        feature.setStyle(new Style({
          stroke: new Stroke({
            color: 'rgba(255, 255, 255, 0.7)',
            width: 2.5,
            lineDash: [6]
          }),
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.1)'
          }),
          text: new Text({
            text: feature.get('massif_num'),
            font: '12px sans-serif',
            fill: new Fill({ color: '#000' }),
            stroke: new Stroke({ color: '#fff', width: 3 }),
            textAlign: 'center'
          })
        }))
        return feature
      })
    },
    // 图层设置
    visableEquipmentleLayer (val) {
      if (val) {
        this.setLayersOrLegends({ obj: 'layers', key: 'equipment', value: true })
        this.setLayersOrLegends({ obj: 'legends', key: 'equipment', value: true })
      } else {
        this.setLayersOrLegends({ obj: 'layers', key: 'equipment', value: false })
        this.setLayersOrLegends({ obj: 'legends', key: 'equipment', value: false })
      }
    }
  },
  mounted () {
    this.initMap()
    this.getToken()
    // this.initVideoPlayer()
  }
}
</script>

<style lang="scss">
.component-map {
  height: 100%;
  position: relative;

  .map {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #e8e8e8;
  }

  .popup {
    width: 260px;
    background-color: rgba(51, 51, 51, 0.8);
    padding: 10px;
    border-radius: 5px;
    color: #ffffff;
    font-size: 14px;
  }

  .map-button-group {
    position: absolute;
    right: 29.5px;
    bottom: 22.5px;
  }
}
.videoPlayer {
  height: 250px;
}
</style>
